package logger

import (
	"fmt"
	"os"
	"time"
)

type Logger interface {
	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warningf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
	Fatalf(format string, args ...interface{})
}

type LogLevel uint8

const (
	debugLevelStr = "DEBUG"
	infoLevelStr = "INFO"
	warningLevelStr = "WARN"
	errorLevelStr = "ERROR"
	fatalLevelStr = "FATAL"
)

func StringByLogLevel(level string) LogLevel {
	switch level {
	case debugLevelStr:
		return DebugLevel
	case infoLevelStr:
		return InfoLevel
	case warningLevelStr:
		return WarningLevel
	case errorLevelStr:
		return ErrorLevel
	case fatalLevelStr:
		return FatalLevel
	default:
		return InfoLevel
	}
}

func (level LogLevel) String() string {
	switch level {
	case DebugLevel:
		return debugLevelStr
	case InfoLevel:
		return infoLevelStr
	case WarningLevel:
		return warningLevelStr
	case ErrorLevel:
		return errorLevelStr
	case FatalLevel:
		return fatalLevelStr
	default:
		return "UNKNOWN"
	}
}

const (
	DebugLevel LogLevel = 5
	InfoLevel LogLevel = 4
	WarningLevel LogLevel = 3
	ErrorLevel LogLevel = 2
	FatalLevel LogLevel = 1
)

type STDLogger struct {
	level LogLevel
}

func NewSTDLogger(level LogLevel) STDLogger {
	l := &STDLogger{}
	l.level = level
	return *l
}

func (l STDLogger) SetLevel(level LogLevel) {
	l.level = level
}

func (l STDLogger) Debugf(format string, args ...interface{}) {
	if l.level >= DebugLevel {
		l.logPrintf(DebugLevel,format,args...)
	}
}

func (l STDLogger) Infof(format string, args ...interface{}) {
	if l.level >= InfoLevel {
		l.logPrintf(InfoLevel,format,args...)
	}
}

func (l STDLogger) Warningf(format string, args ...interface{}) {
	if l.level >= WarningLevel {
		l.logPrintf(WarningLevel, format, args...)
	}
}
func (l STDLogger) Errorf(format string, args ...interface{}) {
	if l.level >= ErrorLevel {
		l.logPrintf(ErrorLevel, format, args...)
	}
}

func (l STDLogger) Fatalf(format string, args ...interface{}) {
	if l.level >= FatalLevel {
		l.logPrintf(FatalLevel, format, args...)
	}
}

func (l STDLogger) logPrefixStr(level LogLevel) string {
	currentTime := time.Now().Format("2006-01-02 15:04:05.0000")
	pid := os.Getegid()
	return fmt.Sprintf("%s [%s] [%d]", currentTime, level.String(), pid)
}

func (l STDLogger) logPrintf(level LogLevel, format string, args ...interface{}) {
	prefixStr := l.logPrefixStr(level)
	content := fmt.Sprintf(format, args...)
	fmt.Printf("%s: %s", prefixStr, content)
}

